﻿using System;
using System.Collections.Generic;

namespace PredatorPrey.Library
{
	// Id		: $Id: Field.cs 39 2009-04-23 21:38:07Z kristof@kristofmattei.be $
	// Date		: $Date: 2009-04-23 21:38:07 +0000 (Thu, 23 Apr 2009) $
	// Author	: $Author: kristof@kristofmattei.be $
	// Revision	: $Revision: 39 $
	/// <summary>
	/// The Field
	/// </summary>
	public class Field : System.Collections.IEnumerable
	{
		/// <summary>
		/// Width of the board (the Y)
		/// </summary>
		public int Width { get; private set; }

		/// <summary>
		/// Height of the board (the X)
		/// </summary>
		public int Height { get; private set; }

		/// <summary>
		/// Container for the Points
		/// </summary>
		private Cell[,] cells;

		/// <summary>
		/// Manipulate a cell
		/// The x &amp; y are 0 based
		/// </summary>
		/// <param name="x">The x location</param>
		/// <param name="y">The y location</param>
		/// <returns>FieldType describing a set of given coordinates</returns>
		public Cell this[int x, int y]
		{
			get
			{
				return this.cells[x, y];
			}
			set
			{
				this.cells[x, y] = value;
			}
		}

		/// <summary>
		/// Manipulate an call
		/// the cell is 0 based
		/// </summary>
		/// <param name="cell">The cell</param>
		/// <returns>FieldType describing a set of given coordinates</returns>
		public Cell this[Cell cell]
		{
			get
			{
				return this[cell.X, cell.Y];
			}
			set
			{
				this[cell.X, cell.Y] = value;
			}
		}

		/// <summary>
		/// Creates a Field
		/// </summary>
		/// <param name="width">The width</param>
		/// <param name="height">The heights</param>
		public Field(int width, int height)
		{
			this.Width = width;
			this.Height = height;

			//assign empty jagged array to cells
			this.cells = new Cell[width, height];
		}

		#region IEnumerable Members

		public System.Collections.IEnumerator GetEnumerator()
		{
			for (int x = 0; x < this.Width; x++)
			{
				for (int y = 0; y < this.Height; y++)
				{
					yield return this[x, y];
				}
			}
		}

		#endregion

		/// <summary>
		/// Creates a list of all the neighbour of a <paramref name="cell"/>
		/// </summary>
		/// <param name="cell">The cell to examine</param>
		/// <returns>A list of surrounding cells which are possible locations</returns>
		public List<Cell> GetNeighbours(Cell cell)
		{
			//we want to return North, East, South and West
			//we might add more here :)

			List<Cell> possibleCells = new List<Cell>();

			//North:
			if (cell.Y + 1 >= this.Height || this[cell.X, cell.Y + 1].FieldType == FieldType.Wall)
			{
				//no north
			}
			else
			{
				possibleCells.Add(new Cell(cell.X, cell.Y + 1, this[cell.X, cell.Y + 1].FieldType));
			}

			//South
			if (cell.Y - 1 <= -1 || this[cell.X, cell.Y - 1].FieldType == FieldType.Wall)
			{
				// no south
			}
			else
			{
				possibleCells.Add(new Cell(cell.X, cell.Y - 1, this[cell.X, cell.Y - 1].FieldType));
			}

			//East
			if (cell.X + 1 >= this.Width || this[cell.X + 1, cell.Y].FieldType == FieldType.Wall)
			{
				//no east
			}
			else
			{
				possibleCells.Add(new Cell(cell.X + 1, cell.Y, this[cell.X + 1, cell.Y].FieldType));
			}

			if (cell.X - 1 <= -1 || this[cell.X - 1, cell.Y].FieldType == FieldType.Wall)
			{
				// no west
			}
			else
			{
				possibleCells.Add(new Cell(cell.X - 1, cell.Y, this[cell.X - 1, cell.Y].FieldType));
			}


			return possibleCells;
		}

		/// <summary>
		/// Searches for a node in the list
		/// </summary>
		/// <param name="fieldType">The fieldtype to be searched for</param>
		/// <returns>The cell which has the specified fieldType</returns>
		public Cell SearchFor(FieldType fieldType)
		{
			foreach (Cell cell in this)
			{
				if (cell.FieldType == fieldType)
					return cell;
			}

			throw new CellNotFoundException("Cell of type " + fieldType + " not found, this usually means a problem with the map");
		}
	}
}